<?php declare(strict_types=1);
/**
 * @author      xianganyall <xianganyall@gmail.com>
 * @copyright   2023-2025 owner
 **/

namespace Srv\Scripts\Cronds;

use Srv\Apps\Proto\Enum\Common\LogoutStatusEnum;
use Srv\Libs\Boot;
use Srv\Libs\Common\CommArray;
use Srv\Libs\Common\CommJson;
use Srv\Libs\Common\CommTime;
use Srv\Libs\Daemon\PhpDaemon;
use Srv\Libs\Frame\AuthData;
use Srv\Libs\Storage\DataMysql;
use Srv\Libs\Tools\ShellPrint;

require_once dirname(__DIR__, 2).'/Libs/Boot.php';
Boot::runConf('');
set_time_limit(0);

// 定时循环执行
(new class extends PhpDaemon
{
    protected string $defaultPidPath                = '';           // default pid file path
    protected string $defaultLogPath                = '';           // default log file path
    protected string $defaultConfPath               = '';           // default config file path
    protected string $defaultTmpPath                = '';           // default tmp file path
    protected int $defaultSleep                     = 3;            // default Sleep time
    private ?DataMysql $DbAuto                      = null;         // DB-Write
    private string $logoutNickName                  = 'Account deleted';    // 注销用户的昵称

    /**
     *  constructor.
     */
    public function __construct()
    {
        $classFileName              = trim(preg_replace("'\\\\'", '_', __CLASS__), '_');
        (preg_match("/^class@anonymous\S+/i", $classFileName)) && $classFileName = basename(__FILE__);
        $pathLogs                   = Boot::getLogsPath();
        $this->defaultTmpPath       = Boot::getTmpPath();
        $this->defaultPidPath       = $pathLogs.'Cronds/'.$classFileName.'.pid';
        $this->defaultLogPath       = $pathLogs.'Cronds/'.$classFileName.'.log';
        $this->pidUrl               = $this->defaultPidPath;
        $this->logUrl               = $this->defaultLogPath;
        $this->confUrl              = $this->defaultConfPath;
        $this->sleep                = $this->defaultSleep;
        parent::__construct();
    }

    /**
     * runInit
     */
    public function runInit():void
    {
        $pId                        = getmypid();
        $this->DbAuto               = DataMysql::tag('auto', 'DBW_'.$pId);
    }

    /**
     * run
     */
    public function run():void
    {
        ShellPrint::printlnString('-- Start -- '.CommTime::getString('Y-m-d H:i:s'));
        // 建议每小时执行
        $pageSize       = 1000;
        $list           = $this->getLogoutApplyList($pageSize);
        $result         = $this->handleLogoutApply($list);
        ShellPrint::printlnString('-- End -- '.CommTime::getString('Y-m-d H:i:s').' -- RESULT -- '.($result?1:0));
        exit();
    }

    /**
     * @param array $list
     * @return bool
     * 处理账号注销
     */
    private function handleLogoutApply(array $list):bool
    {
        if(count($list) < 1) return false;
        // 注销用户相关主要信息 user_info + user_bind_record + user_token_record
        $currTime       = CommTime::getTimeStamp(0);
        foreach ($list as $val){
            $userId                 = $val['userId'];
            $ultrId                 = $val['ultrId'];
            if($ultrId < 1 || $userId < 1) continue;
            $userInfoOld            = $this->DbAuto->getDataOne('SELECT user_id, usi_idnum, usi_nickname, usi_signature, usi_avatar, usi_birthday, usi_gender, usi_cover, usi_active_time, usi_online_time, usi_online_days, usi_finish, usi_finish_time,usi_create_time, usi_update_time FROM '.$this->DbAuto->getTableNameAll('user_info').' WHERE user_id='.$userId.' AND usi_logout=0 AND usi_delete=0');
            if(!isset($userInfoOld['user_id'])) continue;
            $bindList               = $this->DbAuto->getData('SELECT usbr_id, user_id, durt_id, usbr_appid, usbr_openid, usbr_unionid, usbr_token, usbr_enable, usbr_create_time, usbr_update_time FROM '.$this->DbAuto->getTableNameAll('user_bind_record').' WHERE user_id='.$userId.' AND usbr_enable=1 AND usbr_delete=0');
            $tokenKeyOldList        = $this->DbAuto->getData('SELECT utnr_id, utnr_nonce FROM '.$this->DbAuto->getTableNameAll('user_token_record').' WHERE user_id='.$userId.' AND utnr_delete=0 AND utnr_expire_time>='.$currTime);
            $this->DbAuto->startTransaction();
            // 重置用户基本信息
            $sql                    = 'UPDATE '.$this->DbAuto->getTableNameAll('user_info').' SET usi_nickname=\''.$this->DbAuto->getRealEscapeString($this->logoutNickName).'\', usi_signature=\'\', usi_avatar=\'\', usi_birthday=0, usi_gender=0, usi_cover=\'\', usi_active_time=0, usi_online_time=0, usi_online_days=0, usi_tourist=0, usi_tourist_time=0, usi_logout=1, usi_logout_time='.$currTime.', usi_finish=0, usi_finish_time=0 WHERE user_id='.$userId.' AND usi_delete=0';
            if($this->DbAuto->getDataNum($sql) < 1){
                $this->DbAuto->backTransaction();
                continue;
            }
            // 解除绑定关系
            if(count($bindList) > 0){
                foreach ($bindList as $bindInfoOld){
                    $usbrId     = intval($bindInfoOld['usbr_id']??0);
                    if($usbrId < 1) continue;
                    $sql        = 'UPDATE '.$this->DbAuto->getTableNameAll('user_bind_record').' SET usbr_enable=0, usbr_delete=1, usbr_update_time='.$currTime.' WHERE usbr_id='.$usbrId.' AND user_id='.$userId.' AND usbr_enable=1 AND usbr_delete=0';
                    if($this->DbAuto->getDataNum($sql) < 1){
                        $this->DbAuto->backTransaction();
                        continue 2;     // 解除绑定关联失败
                    }
                }
            }
            // 注销当前令牌
            if(count($tokenKeyOldList) > 0){
                $utnrIdList         = [];
                foreach ($tokenKeyOldList as $tokenKeyOld){
                    $utnrId         = intval($tokenKeyOld['utnr_id']??0);
                    $nonceInt       = intval($tokenKeyOld['utnr_nonce']);
                    if($utnrId < 1 || $nonceInt < 1) continue;
                    $utnrIdList[]   = $utnrId;
                    AuthData::delCacheApiTokenKeyData(AuthData::getTokenKeyByNonce($nonceInt), $userId);    // 删除token
                }
                if(count($utnrIdList) > 0){
                    $sql            = 'UPDATE '.$this->DbAuto->getTableNameAll('user_token_record').' SET utnr_delete=1, utnr_update_time='.$currTime.' WHERE utnr_id IN ('.implode(',', $utnrIdList).') AND user_id='.$userId.' AND utnr_delete=0';
                    if($this->DbAuto->getDataNum($sql) < 1){
                        $this->DbAuto->backTransaction();
                        continue;
                    }
                }
            }
            // 更新对应注销记录
            $logoutDataJson = CommJson::encodeArray(['userInfo' => $userInfoOld, 'bindList' => $bindList]);
            $sql            = 'UPDATE '.$this->DbAuto->getTableNameAll('user_logout_record').' SET ultr_review='.LogoutStatusEnum::LOGOUT_STATUS_SUCCESS.', ultr_update_time='.$currTime.', ultr_logout_data=\''.$this->DbAuto->getRealEscapeString($logoutDataJson).'\' WHERE ultr_id='.$ultrId.' AND user_id='.$userId.' AND ultr_review=3 AND auir_id>0 AND ultr_delete=0';
            if($this->DbAuto->getDataNum($sql) < 1){
                $this->DbAuto->backTransaction();
                continue;
            }
            $this->DbAuto->commitTransaction();
        }
        return true;
    }

    /**
     * @param int $pageSize
     * @return array
     * 获取要处理的注销记录
     */
    private function getLogoutApplyList(int $pageSize):array
    {
        $listData       = [];
        if($pageSize < 1) return $listData;
        $currTime       = CommTime::getTimeStamp(0);
        $list           = $this->DbAuto->getData('SELECT ultr_id, user_id FROM '.$this->DbAuto->getTableNameAll('user_logout_record').' WHERE ultr_review='.LogoutStatusEnum::LOGOUT_STATUS_ACCEPT.' AND auir_id>0 AND ultr_delete=0 AND ultr_logout_allow_time<'.$currTime.' ORDER BY ultr_id ASC LIMIT '.$pageSize);
        if(CommArray::isForeach($list)) foreach($list as $val){
            $ultrId     = intval($val['ultr_id']);
            $userId     = intval($val['user_id']);
            if($ultrId < 1 || $userId < 1) continue;
            $listData[] = ['ultrId' => $ultrId, 'userId'=> $userId];
        }
        return $listData;
    }
});

